package com.yanqu.road.dao.impl.activity.suitang;

import com.yanqu.road.dao.db.DBManager;
import com.yanqu.road.dao.db.DbNameStrategy;
import com.yanqu.road.dao.impl.TempDao;
import org.apache.commons.beanutils.BeanUtils;
import java.lang.reflect.InvocationTargetException;
import java.sql.*;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;

public abstract class GenericDao extends TempDao {

    protected DBManager db = getDb(); // Db 是数据库连接管理类

    public <K, T> Map<K, T> executeQuery(
            String sql,
            Object[] params,
            Class<T> type,
            Function<ResultSet, K> keyMapper) {

        Map<K, T> map = new ConcurrentHashMap<>();
        ResultSet rs = null;
        PreparedStatement stmt = null;

        try {
            db.setConnName(DbNameStrategy.getServerDb());
            stmt = db.getConnection().prepareStatement(sql);
            for (int i = 0; i < params.length; i++) {
                stmt.setObject(i + 1, params[i]);
            }

            rs = stmt.executeQuery();
            while (rs.next()) {
                T obj = type.getDeclaredConstructor().newInstance();
                ResultSetMetaData metaData = rs.getMetaData();
                for (int i = 1; i <= metaData.getColumnCount(); i++) {
                    String columnName = metaData.getColumnName(i);
                    Object value = rs.getObject(i);
                    BeanUtils.setProperty(obj, columnName, value);
                }

                K key = keyMapper.apply(rs);
                map.put(key, obj);
            }
        }  catch (SQLException | IllegalAccessException | InvocationTargetException |
                  NoSuchMethodException | InstantiationException e) {
            logger.error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
        } finally {
            db.closeConnection(stmt, rs);
        }

        return map;
    }
}